<!DOCTYPE html>
<html>
  



<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <!-- Global site tag (gtag.js) - Google Analytics -->


  <title>SSM - spring支持的常用数据库事务传播属性和事务隔离级别 | Harbour学习笔记</title>
  
    
<link rel="stylesheet" href="/blog/js/aos/aos.css">

  
  <link rel="icon" type="image/x-icon, image/vnd.microsoft.icon" href="/blog/favicon.ico">
  <link rel="stylesheet" href="https://at.alicdn.com/t/font_1911880_c1nvbyezg17.css">
  <link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  
    <script src="https://cdn.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/autoload.js"></script>
  
  
<link rel="stylesheet" href="/blog/css/animate.min.css">

  
<link rel="stylesheet" href="/blog/css/style.css">

  
  
    
<link rel="stylesheet" href="/blog/js/fancybox/jquery.fancybox.min.css">

  
  
    
<link rel="stylesheet" href="/blog/js/shareJs/share.min.css">

  
  <style>
        @media (max-width: 992px) {
            #waifu {
                display: none;
            }
        }
    </style>
<meta name="generator" content="Hexo 5.2.0"><link rel="stylesheet" href="/blog/css/prism-tomorrow.css" type="text/css"></head>

  
<script src="/blog/js/jquery3.5.1.js"></script>

  
<script src="/blog/js/vue2.6.11.js"></script>

  <body>
    <header class="header bg-color" 
  style="position: fixed; 
  left: 0; top: 0; z-index: 10;width: 100%;"
>
  <div class="header-content">
    <div class="bars">
      <div id="appDrawer" class="sidebar-image">
  <i class="fa fa-bars" aria-hidden="true" @click="showDialogDrawer"></i>
  <div class="drawer-box_mask" v-cloak style="display: none;" v-show="visible" @click.self="cancelDialogDrawer">
  </div>
  <div class="drawer-box" :class="{'active': visible}">
    <div class="drawer-box-head bg-color">
      <img class="drawer-box-head_logo" src="/medias/logo.png" alt="logo">
      <h3 class="drawer-box-head_title">Harbour学习笔记</h3>
      <h5 class="drawer-box-head_desc">大数据程序员一枚</h5>
    </div>
    <div class="drawer-box-content">
      <ul class="drawer-box-content_menu">
        
          <li class="drawer-box-content_item">
            <a href="/blog/" class="menu-item-link">
              
                <i class="fa fa-home" aria-hidden="true"></i>
              
              <span>首页</span>
            </a>
          </li>
        
          <li class="drawer-box-content_item">
            <a href="/blog/archives" class="menu-item-link">
              
                <i class="fa fa-home" aria-hidden="true"></i>
              
              <span>归档</span>
            </a>
          </li>
        
          <li class="drawer-box-content_item">
            <a href="/blog/tags" class="menu-item-link">
              
                <i class="fa fa-tags" aria-hidden="true"></i>
              
              <span>标签</span>
            </a>
          </li>
        
          <li class="drawer-box-content_item">
            <a href="/blog/categories" class="menu-item-link">
              
                <i class="fa fa-bookmark" aria-hidden="true"></i>
              
              <span>分类</span>
            </a>
          </li>
        
          <li class="drawer-box-content_item">
            <a href="/blog/about" class="menu-item-link">
              
                <i class="fa fa-user" aria-hidden="true"></i>
              
              <span>关于</span>
            </a>
          </li>
        
          <li class="drawer-box-content_item">
            <a href="/blog/friends" class="menu-item-link">
              
                <i class="fa fa-link" aria-hidden="true"></i>
              
              <span>友情链接</span>
            </a>
          </li>
        
        <li class="drawer-box-content_item">
          <a href="">
            <i class="fa fa-github" aria-hidden="true"></i>
            <span>Github</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</div>

<script>
  var body = document.body || document.documentElement || window;
  var vm = new Vue({
    el: '#appDrawer',
    data: {
      visible: false,
      top: 0,
    },
    computed: {
    },
    mounted() {
    },
    methods: {
      showDialogDrawer() {
        this.visible = true;
        // 防止页面滚动，只能让弹框滚动
        this.top = $(document).scrollTop()
        body.style.cssText = 'width: 100%; height: 100%; position: fixed; top: -' + this.top  + 'px; left: 0; overflow: hidden;';
      },
      cancelDialogDrawer() {
        this.visible = false;
        body.removeAttribute('style');
        $(document).scrollTop(this.top)
      }
    },
    created() {}
  })
</script>
    </div>
    <div class="blog-title" id="author-avatar">
      <div class="avatar">
        <img src="/medias/logo.png" alt="logo">
      </div>
      <a href="/blog/" class="logo">Harbour学习笔记</a>
    </div>
    <nav class="navbar">
      <ul class="menu">
        
          <li class="menu-item">
            <a href="/blog/" class="menu-item-link">
              
                <i class="fa fa-home" aria-hidden="true"></i>
              
              <span>首页</span>
            </a>
          </li>
        
          <li class="menu-item">
            <a href="/blog/archives" class="menu-item-link">
              
                <i class="fa fa-archive" aria-hidden="true"></i>
              
              <span>归档</span>
            </a>
          </li>
        
          <li class="menu-item">
            <a href="/blog/tags" class="menu-item-link">
              
                <i class="fa fa-tags" aria-hidden="true"></i>
              
              <span>标签</span>
            </a>
          </li>
        
          <li class="menu-item">
            <a href="/blog/categories" class="menu-item-link">
              
                <i class="fa fa-bookmark" aria-hidden="true"></i>
              
              <span>分类</span>
            </a>
          </li>
        
          <li class="menu-item">
            <a href="/blog/about" class="menu-item-link">
              
                <i class="fa fa-user" aria-hidden="true"></i>
              
              <span>关于</span>
            </a>
          </li>
        
          <li class="menu-item">
            <a href="/blog/friends" class="menu-item-link">
              
                <i class="fa fa-link" aria-hidden="true"></i>
              
              <span>友情链接</span>
            </a>
          </li>
        
      </ul>
      
        <div id="appSearch">
  <div class="search"  @click="showDialog()"><i class="fa fa-search" aria-hidden="true"></i></div>
  <div class="message-box_wrapper" style="display: none;" v-cloak v-show="dialogVisible" @click.self="cancelDialogVisible()">
    <div class="message-box">
      <h2>
        <i class="fa fa-search" aria-hidden="true"></i>
        <span class="title">搜索</span>
      </h2>
      <form class="site-search-form">
        <input type="text"
          placeholder="请输入关键字"
          id="local-search-input" 
          @click="getSearchFile()"
          class="st-search-input"
          v-model="searchInput"
        />
      </form>
      <div class="result-wrapper">
        <div id="local-search-result" class="local-search-result-cls"></div>
      </div>
    </div>
  </div>
</div>

<script src="/blog/js/local_search.js"></script>

<script>
  var body = document.body || document.documentElement || window;
  var vm = new Vue({
    el: '#appSearch',
    data: {
      dialogVisible: false,
      searchInput: '',
      top: 0,
    },
    computed: {
    },
    mounted() {
    },
    methods: {
      showDialog() {
        this.dialogVisible = true;
        // 防止页面滚动，只能让弹框滚动
        this.top = $(document).scrollTop()
        body.style.cssText = 'width: 100%; height: 100%; position: fixed; top: -' + this.top  + 'px; left: 0; overflow: hidden;';
      },
      getSearchFile() {
        if (!this.searchInput) {
          getSearchFile();
        }
      },
      cancelDialogVisible() {
        this.dialogVisible = false;
        body.removeAttribute('style');
        $(document).scrollTop(this.top)
      },
    },
    created() {}
  })
</script>
<!-- 解决刷新页面闪烁问题，可以在元素上添加display: none, 或者用vue.extend方法，详情：https://blog.csdn.net/qq_31393401/article/details/81017912 -->
<!-- 下面是搜索基本写法 -->
<!-- <script type="text/javascript" id="local.search.active">
  var inputArea = document.querySelector("#local-search-input");
  inputArea.onclick   = function(){ getSearchFile(); this.onclick = null }
  inputArea.onkeydown = function(){ if(event.keyCode == 13) return false }
</script> -->

      
    </nav>
  </div>
  
  <a target="_blank" rel="noopener" href="https://harbourzhang99.github.io" class="github-corner color-primary" aria-label="View source on GitHub"><svg width="60" height="60" viewBox="0 0 250 250" style="fill:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
</header>
    <main class="main" style="margin-top: 60px;">
      


<div class="post-detail-header" style="background: url(/medias/9.png) no-repeat; background-size: cover; 
  background-position: center center;">
  
    <span class="title">SSM - spring支持的常用数据库事务传播属性和事务隔离级别</span>
  
</div>
<div class="row justify-center">
  <div class="main-content">
    <article class="post post-detail">
      
      
      <div class="post-meta">
        <i class="fa fa-clock-o" aria-hidden="true"></i>
        <span class="post-time">2020-11-11</span>
      </div>
      
      <div class="post-tags-categories">
        
        <div class="tags">
          <i class="iconfont icontag"></i>
          
            <a href="/blog/tags/ssm/" class="">
              ssm
            </a>
          
            <a href="/blog/tags/%E9%9D%A2%E8%AF%95%E9%A2%98/" class="">
              面试题
            </a>
          
            <a href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" class="">
              数据库
            </a>
          
            <a href="/blog/tags/%E4%BA%8B%E5%8A%A1/" class="">
              事务
            </a>
          
        </div>
        
        
      </div>
      <div class="post-content">
        <p>收获：ssm学习笔记。</p>
<a id="more"></a>

<h1 id="spring支持的常用数据库事务传播属性和事务隔离级别"><a href="#spring支持的常用数据库事务传播属性和事务隔离级别" class="headerlink" title="spring支持的常用数据库事务传播属性和事务隔离级别"></a>spring支持的常用数据库事务传播属性和事务隔离级别</h1><p>事务是恢复和<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6">并发控制</a>的基本单位。</p>
<p>事务应该具有4个属性：==原子性、一致性、隔离性、持久性==。这四个属性通常称为<strong>ACID特性</strong>。</p>
<table>
<thead>
<tr>
<th align="center">属性</th>
<th>释义</th>
</tr>
</thead>
<tbody><tr>
<td align="center">原子性（atomicity）</td>
<td>一个事务是一个不可分割的工作单位，事务中包括的操作要么都做，要么都不做。</td>
</tr>
<tr>
<td align="center">一致性（consistency）</td>
<td>事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。</td>
</tr>
<tr>
<td align="center">隔离性（isolation）</td>
<td>一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的，并发执行的各个事务之间不能互相干扰。</td>
</tr>
<tr>
<td align="center">持久性（durability）</td>
<td>持久性也称永久性（permanence），指一个事务一旦提交，它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。</td>
</tr>
</tbody></table>
<h2 id="1-Spring支持的常用数据库事务传播属性和事务隔离级别"><a href="#1-Spring支持的常用数据库事务传播属性和事务隔离级别" class="headerlink" title="1. Spring支持的常用数据库事务传播属性和事务隔离级别"></a>1. Spring支持的常用数据库事务传播属性和事务隔离级别</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//请简单介绍Spring支持的常用数据库事务传播属性和事务隔离级别？</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 事务的属性：</span></span><br><span class="line"><span class="comment"> *     1.★propagation：用来设置事务的传播行为</span></span><br><span class="line"><span class="comment"> *        事务的传播行为：一个方法运行在了一个开启了事务的方法中时，当前方法是使用原来的事务还是开启一个新的事务</span></span><br><span class="line"><span class="comment"> *        -Propagation.REQUIRED：默认值，使用原来的事务</span></span><br><span class="line"><span class="comment"> *        -Propagation.REQUIRES_NEW：将原来的事务挂起，开启一个新的事务</span></span><br><span class="line"><span class="comment"> *     2.★isolation：用来设置事务的隔离级别</span></span><br><span class="line"><span class="comment"> *        -Isolation.REPEATABLE_READ：可重复读，MySQL默认的隔离级别</span></span><br><span class="line"><span class="comment"> *        -Isolation.READ_COMMITTED：读已提交，Oracle默认的隔离级别，开发时通常使用的隔离级别</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<h2 id="2-事务的传播属性："><a href="#2-事务的传播属性：" class="headerlink" title="2. 事务的传播属性："></a>2. 事务的传播属性：</h2><p>当事务方法被另一个事务方法调用时，必须指定事务应该如何传播。例如：方法可能继承在现有事务中运行，也可能开启一个新事务，并在自己的事务中运行。 事务的传播行为可以由传播属性指定。Spring定义了7种类型的传播行为。</p>
<table>
<thead>
<tr>
<th>传播属性</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>REQUIRED （默认）</td>
<td>如果有事务在运行，当前的方法就在这个事务内运行，否则，就启动一个新的事务，并在自己的事务内运行</td>
</tr>
<tr>
<td>REQUIRES_NEW</td>
<td>当前的方法必须启动新的事务，并在它自己的事务内运行，如果有事务正在运行，应该将它挂起</td>
</tr>
<tr>
<td>SUPPORTS</td>
<td>如果有事务正在运行，当前的方法就在这个事务内运行。否则它可以不运行在事务中</td>
</tr>
<tr>
<td>NOT_SUPPORTED</td>
<td>当前的方法不应该运行在事务中。如果有运行的事务，将它挂起</td>
</tr>
<tr>
<td>MANDATORY</td>
<td>当前的方法必须运行在事务内部。如果没有正在运行的事务，就抛出异常</td>
</tr>
<tr>
<td>NEVER</td>
<td>当前的方法不应该运行在事务中。如果有运行的事务,就抛出异常</td>
</tr>
<tr>
<td>NESTED</td>
<td>如果有事务在运行，当前的方法就应该在这个事务的嵌套事务内运行。否则，就启动一个新的事务，并在它自己的事务内运行</td>
</tr>
</tbody></table>
<h2 id="3-事务的隔离级别"><a href="#3-事务的隔离级别" class="headerlink" title="3. 事务的隔离级别"></a>3. 事务的隔离级别</h2><h3 id="1-数据库事务并发问题"><a href="#1-数据库事务并发问题" class="headerlink" title="(1) 数据库事务并发问题"></a>(1) 数据库事务并发问题</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">假设现在有两个事务：Transaction01和Transaction02并发执行</span><br></pre></td></tr></table></figure>

<ul>
<li>==脏读==<ul>
<li>Transaction01 将某条记录的AGE值从20修改为30</li>
<li>Transaction02 读取了 Transaction01 更新后的值：30</li>
<li>Transaction01 回滚，AGE值恢复到了20</li>
<li>Transaction02 读到的30就是一个无效的值</li>
</ul>
</li>
<li>==不可重复读==<ul>
<li>Transaction01读取了AGE值为20</li>
<li>Transaction02将AGE值修改为30</li>
<li>Transaction01再次读取AGE值为30，和第一次读取的不一致</li>
</ul>
</li>
<li>==幻读==<ul>
<li>Transaction01读取了stu表中的一部分数据</li>
<li>Transaction02向stu表中插入了新的行</li>
<li>Transaction01读取stu表时，多出了一些行</li>
</ul>
</li>
</ul>
<h3 id="2-事务的隔离级别"><a href="#2-事务的隔离级别" class="headerlink" title="(2) 事务的隔离级别"></a>(2) 事务的隔离级别</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">数据库系统必须具有隔离并发运行各个事务的能力，使他们不会相互影响，避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了好多事务隔离级别，不同隔离级别对应不同的干扰程度，隔离级别越高，数据一致性就越好，性能开销越大</span><br></pre></td></tr></table></figure>

<ul>
<li><p>==读未提交：<strong>READ UNCOMMITTED</strong>==<br>允许Transaction01读取Transaction02未提交的修改<br>(上面三种情况都不可避免）</p>
</li>
<li><p>==读已提交：<strong>READ COMMITTED</strong>==（常用的，其他事务已经提交的数据都认为是真的）</p>
<p>要求Transaction01只能读取Transaction02已提交的修改<br>（可避免脏读）</p>
</li>
<li><p>==可重复读：<strong>REPEATABLE READ</strong>==<br>确保Transaction01可以多次从一个字段中读取到相同的值，即Transaction01执行期间禁止其他事务对这个字段进行更新。<br>（可避免脏读，不可重复读）</p>
</li>
<li><p>==串行化：<strong>SERIALIZABLE</strong>==<br>确保Transaction01可以从一个表中读取到相同的行，在Transaction01执行期间，禁止其他事务对这个表进行增删改操作。可以避免任何并发问题，但性能十分低下。</p>
</li>
</ul>
<p><strong>各个隔离级别解决并发问题的能力见下表</strong></p>
<table>
<thead>
<tr>
<th>隔离级别</th>
<th>脏读</th>
<th>不可重复读</th>
<th>幻读</th>
</tr>
</thead>
<tbody><tr>
<td>READ UNCOMMITTED</td>
<td>有</td>
<td>有</td>
<td>有</td>
</tr>
<tr>
<td>READ COMMITTED</td>
<td>无</td>
<td>有</td>
<td>有</td>
</tr>
<tr>
<td>REPEATABLE READ</td>
<td>无</td>
<td>无</td>
<td>有</td>
</tr>
<tr>
<td>SERIALIZABLE</td>
<td>无</td>
<td>无</td>
<td>无</td>
</tr>
</tbody></table>
<p><strong>各种数据库产品对事务隔离级别的支持程度</strong></p>
<table>
<thead>
<tr>
<th>隔离级别</th>
<th align="center">Oracle</th>
<th align="center">MySQL</th>
</tr>
</thead>
<tbody><tr>
<td>READ UNCOMMITTED</td>
<td align="center">x</td>
<td align="center">√</td>
</tr>
<tr>
<td>READ COMMITTED</td>
<td align="center">√(默认)</td>
<td align="center">√</td>
</tr>
<tr>
<td>REPEATABLE READ</td>
<td align="center">x</td>
<td align="center">√(默认)</td>
</tr>
<tr>
<td>SERIALIZABLE</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
</tbody></table>

      </div>
      
        <div class="copyright">
  <ul class="post-copyright">
    <li class="post-copyright-author">
    <strong>作者:  </strong>Harbour</a>
    </li>
    <li class="post-copyright-link">
    <strong>文章链接:  </strong>
    <a href="/blog/2020/11/11/SSM面试题[spring支持的常用数据库事务传播属性和事务隔离级别]/" target="_blank" title="SSM - spring支持的常用数据库事务传播属性和事务隔离级别">https://harbourzhang99.gitee.io/blog/2020/11/11/SSM面试题[spring支持的常用数据库事务传播属性和事务隔离级别]/</a>
    </li>
    <li class="post-copyright-license">
      <strong>版权声明:   </strong>
      本网站所有文章除特别声明外,均采用 <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">CC BY-NC-ND 4.0</a>
      许可协议。转载请注明出处!
    </li>
  </ul>
<div>
      
    </article>
    <!-- 上一篇文章和下一篇文章 -->
    
      <div class="post-nav">

  <div class="post-nav-prev post-nav-item">
    <a href="/blog/2020/11/13/Leetcode0005/">
      上一篇:    Leetcode  0005
    </a>
  </div>



  <div class="post-nav-next post-nav-item">
    <a href="/blog/2020/11/11/SSM%E9%9D%A2%E8%AF%95%E9%A2%98%5Bbean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%5D/">
      <span>
        下一篇:    SSM - bean的作用域 
      </span>
    </a>
  </div>

</div>

    
    

    <!-- 打赏 -->
    
      <div id="appDonate" class="post-donate">
  <div id="donate_board" class="donate_bar center" ref="donate">
    <a id="btn_donate" class="btn_donate" href="javascript:;" title="打赏" @click="showDialogDrawer()"></a>
  </div>
  <transition name="fade">
    <div 
      class="donate-box-mask"
      v-cloak 
      v-if="visible"
      @click="cancelDialogDrawer()"
    >
    </div>
  </transition>
  <transition name="bounce">
    <div class="donate-box" v-cloak v-if="visible">
      <div class="donate-box_close">
        <i class="fa fa-times" aria-hidden="true" @click="cancelDialogDrawer"></i>
      </div>
      <div class="donate-box_title">
        <h4>
          你的赏识是我前进的动力
        </h4>
      </div>
      <div class="donate-box_tab">
        <div class="Alipay" :class="{'active': tabActive === 'Alipay'}" @click="changeTabActive('Alipay')">
          支付宝
        </div>
        <div class="WeChatpay" :class="{'active': tabActive === 'WeChatpay'}" @click="changeTabActive('WeChatpay')">
          微信
        </div>
      </div>
      <div class="donate-box_img">
        <div class="AlipayImg" v-if="tabActive === 'Alipay'">
          <img src="/medias/zfb.jpg" alt="支付宝打赏" />
        </div> 
        <div class="WeChatpayImg" v-if="tabActive === 'WeChatpay'">
          <img src="/medias/wx.jpg" alt="微信打赏" />
        </div>
      </div>
    </div>
  </transition>
</div>

<script>
  var body = document.body || document.documentElement || window;
  var vm = new Vue({
    el: '#appDonate',
    data: {
      visible: false,
      tabActive: 'Alipay',
      top: 0,
    },
    computed: {
    },
    mounted() {
    },
    methods: {
      showDialogDrawer() {
        this.visible = true;
        // 防止页面滚动，只能让弹框滚动
        // function getScroll() {
        //   return {
        //     left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
        //     top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
        //   };
        // }
        this.top = $(document).scrollTop() // or getScroll().top
        body.style.cssText = 'width: 100%; height: 100%; position: fixed; top: -' + this.top + 'px; left: 0; overflow: hidden;';
      },
      cancelDialogDrawer() {
        this.visible = false;
        body.removeAttribute('style');
        $(document).scrollTop(this.top)
      },
      changeTabActive(name) {
        this.tabActive = name;
      }
    },
    created() {}
  })
</script>
    

    <!-- 分享 -->
    
      <!-- https://github.com/overtrue/share.js -->

<div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>



<script src="/blog/js/shareJs/social-share.min.js"></script>

</script>

<style>
  .social-share {
    margin: 20px 0;
  }
</style>


    

    <!-- 评论 -->
      
        
      
  </div>

  
    <div class="toc-aside">
      <div class="toc-main">
        <div class="toc-aside-title">
          <i class="fa fa-list-ul" aria-hidden="true"></i><span>目录</span>
        </div>
        <div class="toc-content">
          <link href="/js/tocbot/tocbot.css" rel="stylesheet">
<script src="/js/tocbot/tocbot.min.js"></script>
<div class="toc"></div>

<script>
  if ($('.toc').length > 0) {
    var headerEl = 'h2, h3, h4',  //headers 
      content = '.post-detail',//文章容器
      idArr = {};  //标题数组以确定是否增加索引id
      //add #id

    $(content).children(headerEl).each(function () {
      //去除空格以及多余标点
      var headerId = $(this).text().replace(/[\s|\~|`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\_|\+|\=|\||\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?|\：|\，|\。]/g, '');

      headerId = headerId.toLowerCase();
      if (idArr[headerId]) {
        //id已经存在
        $(this).attr('id', headerId + '-' + idArr[headerId]);
        idArr[headerId]++;
      }
      else {
        //id未存在
        idArr[headerId] = 1;
        $(this).attr('id', headerId);
      }
    });

    tocbot.init({
      // Where to render the table of contents.
      tocSelector: '.toc',
      // Where to grab the headings to build the table of contents.
      contentSelector: content,
      // Which headings to grab inside of the contentSelector element.
      headingSelector: headerEl,
      scrollSmooth: true,
      scrollSmoothOffset: -80,
      headingsOffset: 130,
      positionFixedSelector: '.toc-main',
      positionFixedClass: 'is-position-fixed',
      fixedSidebarOffset: 'auto',
    });
  }

</script>

<style>
.is-position-fixed {
  position:fixed !important;
  top: 64px;
}

</style>
        </div>
      </div>
    </div>
  
</div>

    </main>
    <div class="footer bg-color">
  <div class="footer-main">
    <div class="link">
      <a target="_blank" rel="noopener" href="https://github.com/yuang01/hexo-theme-bamboo">
        <i class="fa fa-github" aria-hidden="true"></i>
      </a>
      <a href="mailto:1730241541@qq.com">
        <i class="fa fa-envelope-o" aria-hidden="true"></i>
      </a>
      <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=1730241541">
        <i class="fa fa-qq" aria-hidden="true"></i>
      </a>
      <a href="/atom.xml" target="_blank">
        <i class="fa fa-rss" aria-hidden="true"></i>
      </a>
    </div>
    <div class="footer-copyright">
      Copyright © 2019 - 2020 <a target="_blank" rel="noopener" href="https://github.com/yuang01">yuang01</a> | Powered by <a target="_blank" rel="noopener" href="https://hexo.io/zh-cn/docs/">Hexo</a> | Theme <a target="_blank" rel="noopener" href="https://github.com/yuang01/theme">Bamboo</a> 
    </div>
    
      
  <!-- 不蒜子统计 -->
  <span id="busuanzi_container_site_pv">
        <i class="fa fa-book" aria-hidden="true"></i>本站总阅读量：<span id="busuanzi_value_page_pv"></span> 次
  </span>
  <span id="busuanzi_container_site_pv">
        <i class="fa fa-eye" aria-hidden="true"></i>本站总访问量：<span id="busuanzi_value_site_pv"></span> 次
  </span>
  <span class="post-meta-divider">|</span>
  <span id="busuanzi_container_site_uv" style='display:none'>
        <i class="fa fa-users" aria-hidden="true"></i>本站访客数：<span id="busuanzi_value_site_uv"></span> 人
  </span>
  <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    
  </div>
</div>


    
      <div class="goTop bg-color">
  <i class="fa fa-arrow-up" aria-hidden="true"></i>
</div>

<script src="/blog/js/goTop.js"></script>

    

    
      <link href="https://cdn.bootcdn.net/ajax/libs/aplayer/1.10.1/APlayer.min.css" rel="stylesheet">
<style>
.aplayer .aplayer-lrc p {
  
  display: none;
  
  font-size: 12px;
  font-weight: 700;
  line-height: 16px !important;
}

.aplayer .aplayer-lrc p.aplayer-lrc-current {
  
  display: none;
  
  font-size: 15px;
  color: #42b983;
}


.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
  left: -66px !important;
}

.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
  left: 0px !important;
}


</style>
<meting-js  
  class=""
  server="netease"
  type="playlist"
  id="442274724"
  fixed='true'
  autoplay='false'
  theme='#42b983'
  loop='all'
  order='random'
  preload='auto'
  volume='0.7'
  list-folded='true'
>
</meting-js>

<!-- <style>
  #aplayer {
    position: fixed;
    left: 0;
    bottom: 300px;
  }
</style> -->
<script src="https://cdn.bootcdn.net/ajax/libs/aplayer/1.10.1/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>
    

    <!-- 图片放大 -->
    
      
<script src="/blog/js/fancybox/jquery.fancybox.min.js"></script>
<script src="/blog/js/wrapImage.js"></script>

    

    <!-- 爱心点击 -->
    
      
<script src="/blog/js/clicklove.js"></script>

    

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script type="text/javascript" size="100" alpha='0.4' zIndex="-1" src="/js/ribbon.min.js"></script>
    
      
<script src="/blog/js/aos/aos.js"></script>

      <script>
        // https://github.com/michalsnik/aos
        const themeOffset = parseInt('120') || 120;
        const themeDelay = parseInt('0')|| 0;
        const themeDuration = parseInt('400') || 400;
        const themeEasing = 'ease' || 'ease';
        const themeOnce = JSON.parse('true' || true);
        const themeMirror = JSON.parse('false' || false);
        const themeAnchorPlacement = 'top-bottom' || 'top-bottom';
        AOS.init({
          // Global settings:
          disable: false, // accepts following values: 'phone', 'tablet', 'mobile', boolean, expression or function
          startEvent: 'DOMContentLoaded', // name of the event dispatched on the document, that AOS should initialize on
          initClassName: 'aos-init', // class applied after initialization
          animatedClassName: 'aos-animate', // class applied on animation
          useClassNames: false, // if true, will add content of `data-aos` as classes on scroll
          disableMutationObserver: false, // disables automatic mutations' detections (advanced)
          debounceDelay: 50, // the delay on debounce used while resizing window (advanced)
          throttleDelay: 99, // the delay on throttle used while scrolling the page (advanced)

          // Settings that can be overridden on per-element basis, by `data-aos-*` attributes:
          offset: themeOffset, // offset (in px) from the original trigger point
          delay: themeDelay, // values from 0 to 3000, with step 50ms
          duration: themeDuration, // values from 0 to 3000, with step 50ms
          easing: themeEasing, // default easing for AOS animations
          once: themeOnce, // whether animation should happen only once - while scrolling down
          mirror: themeMirror, // whether elements should animate out while scrolling past them
          anchorPlacement: themeAnchorPlacement, // defines which position of the element regarding to window should trigger the animation

        });
      </script>
    

    
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/v-plugs-ayu/lib/ayu.css">
<script src="https://cdn.jsdelivr.net/npm/v-plugs-ayu/lib/ayu.umd.min.js"></script>
<div id="appCopy">
</div>
<script>
  var vm = new Vue({
    el: '#appCopy',
    data: {
    },
    computed: {
    },
    mounted() {
      const that = this;
      //  监听 ctrl + c事件  
      $(document).unbind('keypress').bind('keypress', function (e) {
        if (e.ctrlKey && e.keyCode == 67) {
          doSomething();
          // 返回false, 防止重复触发copy事件  
          return false;
        }
      })

      // 鼠标右键的复制事件  
      $(document).unbind('copy').bind('copy', function (e) {
        doSomething();
        // console.log('右键复制 监听成功');
      });

      function doSomething() {
        that.$notify({
          title: '成功',
          content: '复制成功了哦',
          type: 'success'
        })
        // console.log('ctrl + c 监听成功');  
      }
    },
    methods: {
    },
    created() { }
  })
</script>
    

    <!-- 输入框打字特效 -->
    
      
<script src="/blog/js/activate-power-mode.js"></script>

      <script>
          POWERMODE.colorful = true;  // 打开随机颜色特效
          POWERMODE.shake = false;    // 关闭输入框抖动
          document.body.addEventListener('input', POWERMODE);//监听打字事件
      </script>
    

    <!-- markdown代码一键复制功能 -->
    
<script src="/blog/js/clipboard/clipboard.min.js"></script>

    <script>
      !function (e, t, a) {
        var copy = '复制';
        /* code */
        var initCopyCode = function(){
          var copyHtml = '';
          copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
          copyHtml += '<i class="fa fa-globe"></i><span>' + copy + '</span>';
          copyHtml += '</button>';
          $(".post-detail pre code").before(copyHtml);
          new ClipboardJS('.btn-copy', {
              target: function(trigger) {
                  return trigger.nextElementSibling;
              }
          });
        }
        initCopyCode();
      }(window, document);
    </script>
  
  </body>
</html>